package com.informa.unitils.loadstrategies;
import static com.informa.java.util.CollectionUtils.asList;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dbunit.DatabaseUnitException;
import org.dbunit.dataset.Column;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.ReplacementDataSet;
import org.unitils.dbunit.datasetloadstrategy.impl.CleanInsertLoadStrategy;
import org.unitils.dbunit.util.DbUnitDatabaseConnection;

import com.informa.unitils.datasetfactories.valuemappers.LocationBytesMapper;
import com.informa.unitils.datasetfactories.valuemappers.ValueMapper;



public class TransformingDataSetStrategy extends CleanInsertLoadStrategy {

	private List<? extends ValueMapper> mappers = asList(new LocationBytesMapper());
	private Map<String,String> replacementSubstrings = new HashMap<String, String>();
	
	@Override
	public void doExecute(DbUnitDatabaseConnection dbUnitDatabaseConnection,
							IDataSet dataSet) throws DatabaseUnitException, SQLException {

		ReplacementDataSet replacementDataSet = new ReplacementDataSet(dataSet, buildReplacementObjects(dataSet), replacementSubstrings);
		
		super.doExecute(dbUnitDatabaseConnection, replacementDataSet);
	}
	
	private Map<Object,Object> buildReplacementObjects(IDataSet dataSet) throws DataSetException {
		
		Map<Object,Object> replacementObjects = new HashMap<Object, Object>();
		
		for(String tableName : dataSet.getTableNames()) {
			ITable table = dataSet.getTable(tableName);
			for(int row = 0; row < table.getRowCount(); row++) {
				for(Column column : table.getTableMetaData().getColumns()) {
					
					String value = table.getValue(row, column.getColumnName()).toString();

					boolean isPlaceHolder = value.startsWith("${") && value.endsWith("}");
					if (isPlaceHolder) {
						replacementObjects.put(value, replacementFor(value));
					}
						
				}
			}
		}	
		
		return replacementObjects;
		
	}

	private Object replacementFor(String placeHolder) {
		
		String value = placeHolder.substring(2,placeHolder.length() - 1);
		
		for(ValueMapper mapper : mappers) {
			if (mapper.handles(value)) return mapper.map(value);
		}
		
		return placeHolder;
	}	

}
